package com.nofeng.wx.third;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.annotation.JSONField;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.nofeng.wx.utils.IndicatrixUtils;
import com.nofeng.wx.utils.NoHttpsClientUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.boot.web.client.RootUriTemplateHandler;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.URI;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Slf4j
@Service
public class FinanceHttpApi {

    public static final String DATA_API = "http://api.finance.ifeng.com/%s/?code=%s&type=last";

    public static final String DATA_API_60_MINUTE = "https://money.finance.sina.com.cn/quotes_service/api/jsonp_v2.php/a=/CN_MarketData.getKLineData?symbol=%s&scale=60&ma=no&datalen=12000";
    public static final String NOW_API = "http://qt.gtimg.cn/q=%s";

    public static final String DATA_TYPE_DAY = "akdaily";

    public static final String HOT_API="https://push2.eastmoney.com/api/qt/clist/get?cb=&fid=f62&po=1&pz=2000&pn=1&np=1&fltt=2&invt=2&ut=b2884a393a59ad64002292a3e90d46a5&fs=m%3A90+t%3A2&fields=f12%2Cf14%2Cf2%2Cf3%2Cf62%2Cf184%2Cf66%2Cf69%2Cf72%2Cf75%2Cf78%2Cf81%2Cf84%2Cf87%2Cf204%2Cf205%2Cf124%2Cf1%2Cf13";

    public static final String HOT_API_SINA="https://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/MoneyFlow.ssl_bkzj_bk?page=1&num=20&sort=netamount&fenlei=0&asc=";

    public  List<NewsItem> news(int days)throws Exception {
        String httpUrl = "https://www.gov.cn/zhengce/jiedu/";
        RestTemplate restTemplate = NoHttpsClientUtils.getRestTemplate();
        HttpHeaders headers = new HttpHeaders();
        HttpEntity<String> httpEntity=new HttpEntity(headers);
        String result = restTemplate.exchange(httpUrl, HttpMethod.GET, httpEntity, String.class).getBody();
        List<NewsItem> items = new ArrayList<>();
        String regex = "<li>\\s*<h4>\\s*<a href=\"([^\"]+)\"[^>]*>(.*?)</a>\\s*<span class=\"date\">(.*?)</span>\\s*</h4>\\s*</li>";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(result);

        while (matcher.find()) {
            String url = matcher.group(1);
            String title = matcher.group(2);
            if (url.startsWith("../")) {
                // 替换为固定基础路径
                url="https://www.gov.cn/zhengce" + url.substring(2);
            }
            String date = matcher.group(3);
            items.add(new NewsItem(title, url, date));
        }

        LocalDate today = LocalDate.now();
        LocalDate cutoffDate = today.minusDays(days);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        return items.stream()
                .filter(item -> {
                    try {
                        LocalDate publishDate = LocalDate.parse(item.getDate(), formatter);
                        return publishDate.isAfter(cutoffDate);
                    } catch (Exception e) {
                        // 忽略格式错误的数据
                        return false;
                    }
                })
                .collect(Collectors.toList());
    }

    public static class  NewsItem {
        private String title;
        private String url;
        private String date;

        public NewsItem(String title, String url, String date) {
            this.title = title;
            this.url = url;
            this.date = date;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public String getUrl() {
            return url;
        }

        public void setUrl(String url) {
            this.url = url;
        }

        public String getDate() {
            return date;
        }

        public void setDate(String date) {
            this.date = date;
        }
    }

        public List<HttpHotSector> hot(Boolean isIn)throws Exception{
        RestTemplate restTemplate = NoHttpsClientUtils.getRestTemplate();
        HttpHeaders headers = new HttpHeaders();
        HttpEntity<String> httpEntity=new HttpEntity(headers);
        String url=HOT_API_SINA+(isIn?"0":"1");
        String result = restTemplate.exchange(url, HttpMethod.GET,httpEntity,String.class).getBody();
        List<HttpHotSector> hotSectors = JSON.parseObject(
                result,
                new TypeReference<List<HttpHotSector>>() {}
        );
        return hotSectors;
    }

    public static List<HttpHotSector> getHotForEstMoney(Boolean isIn,int length){
        try {
            String getHotForEstMoneyString = getHotForEstMoneyString();
            // 1. 解析整个JSON对象
            JSONObject jsonObject = JSON.parseObject(getHotForEstMoneyString);

            // 2. 提取"data"数组
            JSONArray dataArray = jsonObject.getJSONObject("data").getJSONArray("diff");

            List<HttpHotSector> hotSectors = JSON.parseObject(
                    dataArray.toJSONString(),
                    new TypeReference<List<HttpHotSector>>() {
                    }
            );

            if (!isIn) {
                Collections.sort(hotSectors, (s1, s2) -> {
                    // 将f66转换为数值类型比较（例如Double）
                    return s1.getF66().compareTo(s2.getF66()); // 降序排序
                });
            }

            List<HttpHotSector> top5 = hotSectors.stream()
                    .limit(length)  // 取前5个元素
                    .collect(Collectors.toList());
            return top5;
        }catch (Exception e){
            return Lists.newArrayList();
        }
    }

    public static String get300Pe(){
        String url="http://value500.com/CSI300.asp";
        String result ="";
        try {
            result = NoHttpsClientUtils.getRestTemplate().getForObject(url, String.class);
            result=StringUtils.substringBetween(result,"滚动市盈率：","'");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public static String get500Pe(){
        String url="http://value500.com/000905SHPEPB.asp";
        String result ="";
        try {
            result = NoHttpsClientUtils.getRestTemplate().getForObject(url, String.class);
            result=StringUtils.substringBetween(result,"滚动市盈率：","'");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public static String getCYPe(){
        String url="http://value500.com/399006SZPEPB.asp";
        String result ="";
        try {
            result = NoHttpsClientUtils.getRestTemplate().getForObject(url, String.class);
            result=StringUtils.substringBetween(result,"滚动市盈率：","'");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }


    public static String getHotForEstMoneyString() {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            HttpGet request = new HttpGet("https://push2.eastmoney.com/api/qt/clist/get?" +
                    "cb=&fid=f62&po=1&pz=2000&pn=1&np=1&fltt=2&invt=2&ut=b2884a393a59ad64002292a3e90d46a5&" +
                    "fs=m%3A90+t%3A2&fields=f12%2Cf14%2Cf2%2Cf3%2Cf62%2Cf184%2Cf66%2Cf69%2Cf72%2Cf75%2Cf78%2Cf81%2Cf84%2Cf87%2Cf204%2Cf205%2Cf124%2Cf1%2Cf13");

            // 设置请求头（示例）
            request.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36");

            try (CloseableHttpResponse response = httpClient.execute(request)) {
                int statusCode = response.getStatusLine().getStatusCode();
                if (statusCode == 200) {
                    String result = EntityUtils.toString(response.getEntity());

                    System.out.println(result);
                    return result;
                } else {
                    System.err.println("请求失败，状态码：" + statusCode);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "{}";
    }
    public List<HttpStockData> get(String code, String type) throws Exception {
        String apiCode = convertCode(code);
        String api = String.format(DATA_API, type, apiCode);
        String result = NoHttpsClientUtils.getRestTemplate().getForObject(api, String.class);
        JSONArray jsonArray = JSONObject.parseObject(result).getJSONArray("record");
        List<String> resultList = jsonArray.toJavaList(String.class);
        List<HttpStockData> stockDayList = resultList.stream().map(this::convertSockDay).collect(Collectors.toList());
        for (HttpStockData httpStockData : stockDayList) {
            httpStockData.setStockCode(code);
        }
        return stockDayList;
    }

    public List<HttpStockData> getMinute(String code) throws Exception {
        String apiCode = convertCode(code);
        String api = String.format(DATA_API_60_MINUTE,  apiCode);
        String result = NoHttpsClientUtils.getRestTemplate().getForObject(api, String.class);
        String filterResult = StringUtils.substringAfter(result, "*/");
        filterResult = StringUtils.replace(filterResult, "a=(", "");
        filterResult = filterResult.substring(0, filterResult.length() - 2);
        JSONArray jsonArray = JSON.parseArray(filterResult);
        LinkedHashMap<String,List<HttpStockData>> minuteMap= Maps.newLinkedHashMap();
        for (int j = 0; j < jsonArray.size(); j++) {
            JSONObject jsonObject = jsonArray.getJSONObject(j);
            HttpStockData httpStockData = convertSockDay(jsonObject);
            if(!minuteMap.containsKey(httpStockData.getCurDate())){
                minuteMap.put(httpStockData.getCurDate(),Lists.newArrayList());
            }
            minuteMap.get(httpStockData.getCurDate()).add(httpStockData);
        }

        List<HttpStockData> stockDayList = Lists.newArrayList();
        for (String s : minuteMap.keySet()) {
            List<HttpStockData> httpStockDataList = minuteMap.get(s);
            if(CollectionUtils.isNotEmpty(httpStockDataList)){
                stockDayList.add(httpStockDataList.get(httpStockDataList.size()-1)) ;
            }
        }


        for (HttpStockData httpStockData : stockDayList) {
            httpStockData.setStockCode(code);
        }
        return stockDayList;
    }


    public static List<HttpStockData> getNow(String codes)throws Exception {
        List<HttpStockData> list = Lists.newArrayList();
        String apiCode = convertCode(codes);
        String api = String.format(NOW_API, apiCode);
        String apiResult = NoHttpsClientUtils.getRestTemplate().getForObject(api, String.class);
        apiResult = StringUtils.replace(apiResult, "\n", "");
        String[] apiResultArry = StringUtils.split(apiResult, ";");
        for (String s : apiResultArry) {
            HttpStockData stockDay =null;
            if(codes.contains("_")) {
                stockDay= nowToStockDayValue(s);
            }else{
                stockDay= nowToStockDayValue2(s);
            }
            list.add(stockDay);
        }

        return list;
    }

    public HttpStockData getUSDCNH() {
        try {
            String api = "https://api-ddc-wscn.awtmt.com/market/kline?prod_code=USDCNH.OTC&tick_count=1&period_type=300&adjust_price_type=forward&fields=close_px";
            RestTemplate restTemplate = NoHttpsClientUtils.getRestTemplate();
            String apiResult = restTemplate.getForObject(api, String.class);
            JSONObject resp = JSONObject.parseObject(apiResult);

            JSONObject usdcnh =resp.getJSONObject("data").getJSONObject("candle").getJSONObject("USDCNH.OTC");

            JSONArray jsonArray = usdcnh.getJSONArray("lines");
            String close = jsonArray.toJavaList(String.class).get(0).replace("[", "").replace("]", "");
            String open=usdcnh.getString("pre_close_px");
            HttpStockData stockDay=new HttpStockData();
            stockDay.setOpen(BigDecimal.valueOf(Double.valueOf(open)));
            stockDay.setClose(BigDecimal.valueOf(Double.valueOf(close)));
            stockDay.setStockCode("USDCNH.OTC");
            return stockDay;
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public  static String convertCode(String code) {
        if (Integer.valueOf(6).equals(StringUtils.length(code))) {
            if (StringUtils.startsWithAny(code, "5", "6", "9")) {
                return "sh" + code;
            } else {
                return "sz" + code;
            }
        }
        return code;
    }

    public static HttpStockData nowToStockDayValue(String now) {
        HttpStockData stockDay = new HttpStockData();
        stockDay.setOpen(new BigDecimal("0"));
        stockDay.setHigh(new BigDecimal("0"));
        stockDay.setClose(new BigDecimal("0"));
        stockDay.setLow(new BigDecimal("0"));
        stockDay.setVolume(new BigDecimal("0"));
        stockDay.setChg(new BigDecimal("0"));
        stockDay.setChgP(new BigDecimal("0"));
        stockDay.setMa5(new BigDecimal("0"));
        stockDay.setMa10(new BigDecimal("0"));
        stockDay.setMa20(new BigDecimal("0"));

        String splitStr = StringUtils.substringAfter(now, "=").replaceAll("\"", "").replaceAll(";", "");
        String[] splitStrArr = splitStr.split("~");
        Date nowDate = new Date();
        String curDate = DateFormatUtils.format(nowDate, FastDateFormat.getInstance("yyyyMMdd").getPattern());
        stockDay.setCurDate(curDate);
        stockDay.setStockName(splitStrArr[1]);
        stockDay.setClose(new BigDecimal(splitStrArr[3]));
        stockDay.setHigh(new BigDecimal(splitStrArr[4]));
        stockDay.setLow(new BigDecimal(splitStrArr[5]));
        if(null!=splitStrArr[5] &&StringUtils.isNotEmpty(splitStrArr[5])) {
            stockDay.setChgP(new BigDecimal(splitStrArr[5]));
        }
        if(null!=splitStrArr[8] &&StringUtils.isNotEmpty(splitStrArr[8])) {
            BigDecimal total = new BigDecimal(new BigDecimal(splitStrArr[8]).doubleValue());
            stockDay.setVolume(total);
        }

        if(null!=splitStrArr[7]&&StringUtils.isNotEmpty(splitStrArr[7])){
            BigDecimal volumeMoney = new BigDecimal(new BigDecimal(splitStrArr[7]).doubleValue());
            stockDay.setVolumeMoney(volumeMoney);
        }
        return stockDay;
    }

    public static HttpStockData nowToStockDayValue2(String now) {
        HttpStockData stockDay = new HttpStockData();
        stockDay.setOpen(new BigDecimal("0"));
        stockDay.setHigh(new BigDecimal("0"));
        stockDay.setClose(new BigDecimal("0"));
        stockDay.setLow(new BigDecimal("0"));
        stockDay.setVolume(new BigDecimal("0"));
        stockDay.setChg(new BigDecimal("0"));
        stockDay.setChgP(new BigDecimal("0"));
        stockDay.setMa5(new BigDecimal("0"));
        stockDay.setMa10(new BigDecimal("0"));
        stockDay.setMa20(new BigDecimal("0"));

        String splitStr = StringUtils.substringAfter(now, "=").replaceAll("\"", "").replaceAll(";", "");
        String[] splitStrArr = splitStr.split("~");
        Date nowDate = new Date();
        String curDate = DateFormatUtils.format(nowDate, FastDateFormat.getInstance("yyyyMMdd").getPattern());
        stockDay.setCurDate(curDate);
        stockDay.setStockName(splitStrArr[1]);
        stockDay.setClose(new BigDecimal(splitStrArr[3]));
        stockDay.setHigh(new BigDecimal(splitStrArr[33]));
        stockDay.setLow(new BigDecimal(splitStrArr[34]));
        if(null!=splitStrArr[32] &&StringUtils.isNotEmpty(splitStrArr[32])) {
            stockDay.setChgP(new BigDecimal(splitStrArr[32]));
        }
        if(null!=splitStrArr[8] &&StringUtils.isNotEmpty(splitStrArr[8])) {
            BigDecimal total = new BigDecimal(new BigDecimal(splitStrArr[8]).doubleValue());
            stockDay.setVolume(total);
        }

        if(null!=splitStrArr[7]&&StringUtils.isNotEmpty(splitStrArr[7])){
            BigDecimal volumeMoney = new BigDecimal(new BigDecimal(splitStrArr[7]).doubleValue());
            stockDay.setVolumeMoney(volumeMoney);
        }
        return stockDay;
    }

    public HttpStockData convertSockDay(JSONObject jsonObject) {
        HttpStockData stockDay = new HttpStockData();
        String day = StringUtils.substringBefore(jsonObject.getString("day"), " ").replaceAll("\"","");
        stockDay.setCurDate(day);
        stockDay.setClose(new BigDecimal(jsonObject.getDouble("close")));
        return stockDay;
    }
    public HttpStockData convertSockDay(String data) {
        HttpStockData stockDay = new HttpStockData();
        JSONArray jsonArray = JSONObject.parseArray(data);
        stockDay.setCurDate(jsonArray.get(0).toString());
        stockDay.setCurDate(StringUtils.replaceEach(stockDay.getCurDate(), new String[]{"-"}, new String[]{""}));
        stockDay.setOpen(new BigDecimal(jsonArray.get(1).toString()));
        stockDay.setHigh(new BigDecimal(jsonArray.get(2).toString()));
        stockDay.setClose(new BigDecimal(jsonArray.get(3).toString()));
        stockDay.setLow(new BigDecimal(jsonArray.get(4).toString()));
        stockDay.setVolume(new BigDecimal(jsonArray.get(5).toString()));
        stockDay.setChg(new BigDecimal(jsonArray.get(6).toString()));
        stockDay.setChgP(new BigDecimal(jsonArray.get(7).toString()));
        stockDay.setMa5(new BigDecimal(jsonArray.get(8).toString().replace(",", "")));
        stockDay.setMa10(new BigDecimal(jsonArray.get(9).toString().replace(",", "")));
        stockDay.setMa20(new BigDecimal(jsonArray.get(10).toString().replace(",", "")));
        return stockDay;
    }

    public static class HttpHotSector{

        @JSONField(name = "f66")
        private BigDecimal f66; //流入量

        @JSONField(name = "f14")
        private String hotSector;

        public BigDecimal getF66() {
            return f66;
        }

        public void setF66(BigDecimal f66) {
            this.f66 = f66;
        }

        public String getHotSector() {
            return hotSector;
        }

        public void setHotSector(String hotSector) {
            this.hotSector = hotSector;
        }
    }

    public static class HttpStockData {
        private String stockCode;
        private String stockName;
        private String curDate;
        private BigDecimal open;
        private BigDecimal high;
        private BigDecimal close;
        private BigDecimal low;
        private BigDecimal volume;
        private BigDecimal volumeMoney;
        private BigDecimal chg;
        private BigDecimal chgP;
        private BigDecimal ma5;
        private BigDecimal ma10;
        private BigDecimal ma20;
        private BigDecimal pe;
        private BigDecimal rsi;

        private BigDecimal ma14;
        private BigDecimal ma60;
        private Boolean overMa20;
        private Double atr60;
        private Double atr60Chp;
        private BigDecimal cutPrice;
        private BigDecimal buyPrice;
        private BigDecimal prePrice;

        public BigDecimal getBuyPrice() {
            return buyPrice;
        }

        public void setBuyPrice(BigDecimal buyPrice) {
            this.buyPrice = buyPrice;
        }

        public BigDecimal getPrePrice() {
            return prePrice;
        }

        public void setPrePrice(BigDecimal prePrice) {
            this.prePrice = prePrice;
        }

        public Double getAtr60Chp() {
            return atr60Chp;
        }

        public void setAtr60Chp(Double atr60Chp) {
            this.atr60Chp = atr60Chp;
        }

        public BigDecimal getCutPrice() {
            return cutPrice;
        }

        public void setCutPrice(BigDecimal cutPrice) {
            this.cutPrice = cutPrice;
        }

        public Double getAtr60() {
            return atr60;
        }

        public void setAtr60(Double atr60) {
            this.atr60 = atr60;
        }

        public Boolean getOverMa20() {
            return overMa20;
        }

        public void setOverMa20(Boolean overMa20) {
            this.overMa20 = overMa20;
        }

        public BigDecimal getRsi() {
            return rsi;
        }

        public void setRsi(BigDecimal rsi) {
            this.rsi = rsi;
        }

        public BigDecimal getMa14() {
            return ma14;
        }

        public void setMa14(BigDecimal ma14) {
            this.ma14 = ma14;
        }

        public BigDecimal getMa60() {
            return ma60;
        }

        public void setMa60(BigDecimal ma60) {
            this.ma60 = ma60;
        }

        public String getStockCode() {
            return stockCode;
        }

        public void setStockCode(String stockCode) {
            this.stockCode = stockCode;
        }

        public String getCurDate() {
            return curDate;
        }

        public void setCurDate(String curDate) {
            this.curDate = curDate;
        }

        public BigDecimal getOpen() {
            return open;
        }

        public void setOpen(BigDecimal open) {
            this.open = open;
        }

        public BigDecimal getHigh() {
            return high;
        }

        public void setHigh(BigDecimal high) {
            this.high = high;
        }

        public BigDecimal getClose() {
            return close;
        }

        public void setClose(BigDecimal close) {
            this.close = close;
        }

        public BigDecimal getLow() {
            return low;
        }

        public void setLow(BigDecimal low) {
            this.low = low;
        }

        public BigDecimal getVolume() {
            return volume;
        }

        public void setVolume(BigDecimal volume) {
            this.volume = volume;
        }

        public BigDecimal getChg() {
            return chg;
        }

        public void setChg(BigDecimal chg) {
            this.chg = chg;
        }

        public BigDecimal getChgP() {
            return chgP;
        }

        public void setChgP(BigDecimal chgP) {
            this.chgP = chgP;
        }

        public BigDecimal getMa5() {
            return ma5;
        }

        public void setMa5(BigDecimal ma5) {
            this.ma5 = ma5;
        }

        public BigDecimal getMa10() {
            return ma10;
        }

        public void setMa10(BigDecimal ma10) {
            this.ma10 = ma10;
        }

        public BigDecimal getMa20() {
            return ma20;
        }

        public void setMa20(BigDecimal ma20) {
            this.ma20 = ma20;
        }

        public String getStockName() {
            return stockName;
        }

        public void setStockName(String stockName) {
            this.stockName = stockName;
        }

        public BigDecimal getPe() {
            return pe;
        }

        public void setPe(BigDecimal pe) {
            this.pe = pe;
        }

        public BigDecimal getVolumeMoney() {
            return volumeMoney;
        }

        public void setVolumeMoney(BigDecimal volumeMoney) {
            this.volumeMoney = volumeMoney;
        }
    }
}
